<?php

namespace App\Services;

use App\Models\CustomerModel;
use App\Models\MessageModel;
use App\Models\RoomModel;
use App\Models\UsersModel;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

class ChatRoomService
{
    /**
     * 在线客服缓存房间
     * @var string $customerRoom
     */
    private static $customerRoom = 'chat_room';

    /**
     * 在线用户聊天房间
     * @var string $userRoom
     */
    private static $userRoom = 'user_room';

    /**
     * 缓存客服服务列表
     * @var string $room
     */
    private static $customerServiceList = 'customer_service_list:';

    /**
     * 服务开启的房间通道
     * @var string $serviceRoom
     */
    private static $serviceRoom = 'customer_service_room';

    /**
     * 客服上线
     * @param int $customer_id
     * @param int $fd
     * @return array
     */
    public function customerOnline(int $customer_id, int $fd) : array
    {
        // 判断客服是否存在
        $customer = CustomerModel::status()->where('id', $customer_id)->first(['id', 'username', 'avatar']);
        if (is_null($customer)) {
            return [];
        }

        // 客服上线了 加入到redis 队列中
        $customer = $customer->toArray();
        $customer = array_merge($customer, ['fd' => $fd, 'user_type' => 2, 'room_id' => 0]);

        // 设置客服上线状态 并且缓存客服信息 下线后清空
        CustomerModel::where('id', $customer_id)->update(['is_online' => 1]);
        Redis::hSet(self::$customerRoom, $customer_id, serialize($customer));

        // 设置通道的用户信息
        $this->setCacheUserData($fd, array_merge($customer));

        return $customer;
    }

    /**
     * 获取当前在线的客服
     * @param int $fd
     * @param int $user_id
     * @return array
     */
    public function userOnline(int $fd, int $user_id = 0) : array
    {
        // 获取以为随机客服
        $customer = $this->getServiceCustomer($user_id);
        if (empty($customer)) {
            return [];
        }

        // 获取用户
        if ($user_id > 0) {
            $user_info = UsersModel::where('id', $user_id)->first(['id', 'username', 'avatar']);
            $user_info = empty($user_info) ? [] : $user_info->toArray();
        } else {
            $user_info = config('default.tourists');
        }

        // 组合用户数据
        $user_type = $user_id > 0 ? 1 : 3;
        $user_data = [
            'fd'          => $fd,
            'customer'    => $customer,
            'room_id'     => $customer['room_id'],
            'user_type'   => $user_type,
            'online_time' => date('H:i:s', \time())
        ];

        $user_info = array_merge($user_info, $user_data);

        $this->setCacheUserData($fd, $user_info);
        // 开启服务房间
        Redis::hSet(self::$serviceRoom, $customer['room_id'], $customer['fd'] . '-' . $fd);
        // 缓存客服服务列表
        Redis::sAdd(self::$customerServiceList . $customer['fd'], $fd);

        return $user_info;
    }

    /**
     * 客服下线
     * @return array
     */
    public function customerLogoff(array $user_info) : array
    {
        // 客服下线 判断客服是否还有服务列表
        // $users = Redis::sMembers(self::$customerServiceList . $user_info);
        // var_dump($users);
/*        $room_info = $this->getRoomInfo($room_id);
        $room_info = explode('-', $room_info);
        Redis::hDel(self::$customerRoom, $room_info[0]);
        CustomerModel::where('id', $customer_id)->update(['is_online' => 0]);*/

        // 获取所有正在服务的列表
    }

    /**
     * 用户下线
     * @param array $user_info
     * @return void
     */
    public function userLogoff(array $user_info)
    {
        // 用户下线后 删除缓存
        Redis::hDel(self::$userRoom, $user_info['fd']);
        // 解除房间号
        Redis::hDel(self::$serviceRoom, $user_info['room_id']);
        // 将用户移出出服务列表
        Redis::sRem(self::$customerServiceList . $user_info['customer']['fd'], $user_info['fd']);
    }

    /**
     * 从客服房间中随机拿出以为客服服务
     * @param int $user_id
     * @return array
     */
    public function getServiceCustomer(int $user_id = 0) : array
    {
        // 先从房间中获取所有在线的客服
        $room_keys = Redis::hKeys(self::$customerRoom);
        if (empty($room_keys)) {
            return [];
        }

        // 如果是用户 有限获取 之前服务过用的客服
        if ($user_id > 0) {
            $service_log = DB::table('room')->where('user_id', $user_id)->pluck('id', 'c_id')->toArray();
            if (count($service_log) > 0) {
                // 取交集
                $history_and_online = array_values(array_intersect($room_keys, array_keys($service_log)));
                if (count($history_and_online) > 0) {
                    $customer_id = $history_and_online[array_rand($history_and_online, 1)];
                    $customer    = Redis::hGet(self::$customerRoom, $customer_id);
                    $customer    = unserialize($customer);
                    $room_id     = $service_log[$customer_id];
                    // 增加服务次数 和 修改最后一次服务开始时间
                    DB::table('room')->where('id', $room_id)->increment('times', 1);
                    DB::table('room')->where('id', $room_id)->update(['last_time' => \time()]);

                    return array_merge($customer, ['room_id' => $service_log[$customer_id], 'start_time' => \time()]);
                }
            }
        }

        // 如果没有历史服务记录 或者是游客 直接从房间中 随机抽取
        $customer_id = $room_keys[array_rand($room_keys, 1)];
        $customer    = Redis::hGet(self::$customerRoom, $customer_id);
        $customer    = unserialize($customer);
        $room_id     = $this->getRoomId($customer_id, $user_id);

        return array_merge($customer, ['room_id' => $room_id, 'start_time' => \time()]);
    }

    /**
     * 获取房间号
     * @param int $customer_id
     * @param int $user_id
     * @return int
     */
    public function getRoomId(int $customer_id, int $user_id) : int
    {
        $room_data = [
            'user_id'     => $user_id,
            'c_id'        => $customer_id,
            'create_time' => \time(),
            'last_time'   => \time()
        ];

        $room = RoomModel::create($room_data);
        return $room->id;
    }

    /**
     * 缓存聊天消息记录
     * @param array $msg_data
     * @return void
     */
    public function cacheChatMessage(array $msg_data)
    {
        MessageModel::create(array_merge($msg_data, ['chat_time' => \time()]));
    }

    /**
     * 获取当前房间中的两个链接
     * @param int $room_id
     * @return string
     */
    public function getRoomInfo(int $room_id) : string
    {
        $room_info = Redis::hGet(self::$serviceRoom, $room_id);
        return empty($room_info) ? '' : $room_info;
    }

    /**
     * 获取缓存的用户信息
     * @param int $fd
     * @return array
     */
    public function getCacheUserData(int $fd) : array
    {
        $user_data = Redis::hGet(self::$userRoom, $fd);
        return empty($user_data) ? [] : unserialize($user_data);
    }

    /**
     * 缓存用户信息
     * @param int $fd
     * @param array $user_data
     * @return void
     */
    public function setCacheUserData(int $fd, array $user_data)
    {
       Redis::hSet(self::$userRoom, $fd, serialize($user_data));
    }
}
